﻿using System;
using System.ComponentModel;
using LocalOverride.Fiddler.Store;

namespace LocalOverride.Fiddler.UI
{
    public class MappingEditorPresenter
    {
        private readonly IMappingEditorView view;
        private readonly IMappingStore store;
        private EditMode editMode;
        private MappingEntry currentEditMapping;
        public const int MaxLogLines = 1000;

        public MappingEditorPresenter(IMappingEditorView view, IMappingStore store)
        {
            this.view = view;
            this.store = store;
            view.AddOverride += ViewAddOverride;
            view.CancelOverrideEdit += ViewCancelOverrideEdit;
            view.SaveOverrideEdit += ViewSaveOverrideEdit;
            view.EditOverride += ViewEditOverride;
            view.DeleteOverride += ViewDeleteOverride;
            view.HideOverrideEditor();
            UpdateViewWithMappingsFromStore();
        }

        

        void ViewDeleteOverride(object sender, DeleteOverrideEventArgs e)
        {
            store.RemoveEntry(e.Mapping);
            store.Persist();
            UpdateViewWithMappingsFromStore();
        }

        private void UpdateViewWithMappingsFromStore()
        {
            var mappingList = new BindingList<MappingEntry>();

            foreach (var mappingEntry in store.Entries)
            {
                mappingList.Add(mappingEntry);
            }
            view.MappingList = mappingList;
        }

        void ViewSaveOverrideEdit(object sender, EventArgs e)
        {
            MappingEntry mappingEntry;
            switch (editMode)
            {
                case EditMode.Add:
                    {
                        mappingEntry = new MappingEntry();
                    }
                    break;
                case EditMode.Update:
                    {
                        mappingEntry = currentEditMapping;
                    }
                    break;
                default:
                    throw new InvalidOperationException("Unknown EditMode");
            }

            mappingEntry.BeginChange();

            var validationResult  = FillMappingEntryFromView(mappingEntry);

            if(validationResult.IsValid)
                validationResult = store.ValidatorFor(mappingEntry).Validate();
            
            if (validationResult.IsValid)
            {
                if (editMode == EditMode.Add)
                {
                    store.AddEntry(mappingEntry);
                }
                view.HideOverrideEditor();
                store.Persist();
            }
            else
            {
                mappingEntry.CancelChange();
                view.SetErrors(validationResult.Errors);
            }

            UpdateViewWithMappingsFromStore();
            
        }

        private ValidationResult FillMappingEntryFromView(MappingEntry mappingEntry)
        {
            mappingEntry.Url = view.EditUrl;
            mappingEntry.LocalPath = view.EditLocalPath;
            mappingEntry.IsDirectory = view.IsDirectory;
            mappingEntry.DownloadLocalCopy = view.DownloadLocalCopy;
            mappingEntry.DefaultFileName = view.EditDefaultFileName;
            try
            {
                mappingEntry.FileExtensions = ExtensionMapper.ToStore(view.EditExtensions);
            }
            catch(ArgumentException)
            {
                return new ValidationResult(false, new ErrorNotification("Extensions", "Invalid Extensions"));
            }

            return ValidationResult.Valid;
        }

        void ViewCancelOverrideEdit(object sender, EventArgs e)
        {
            view.HideOverrideEditor();
        }

        public IMappingEditorView View
        {
            get { return view; }
        }

        void ViewAddOverride(object sender, EventArgs e)
        {
            view.EditUrl = string.Empty;
            view.EditLocalPath = string.Empty;
            view.IsDirectory = false;
            view.EditDefaultFileName = "index.html";
            editMode = EditMode.Add;
            view.ClearErrors();
            view.ShowOverrideEditor();
        }

        void ViewEditOverride(object sender, EditOverrideEventArgs e)
        {
            view.EditUrl = e.Mapping.Url;
            view.EditLocalPath = e.Mapping.LocalPath;
            view.IsDirectory = e.Mapping.IsDirectory;
            view.EditExtensions = ExtensionMapper.ToString(e.Mapping.FileExtensions);
            view.EditDefaultFileName = e.Mapping.DefaultFileName;
            view.DownloadLocalCopy = e.Mapping.DownloadLocalCopy;

            currentEditMapping = e.Mapping;
            editMode = EditMode.Update;
            
            var validationResult = store.ValidatorFor(e.Mapping).Validate();
            
            if(!validationResult.IsValid)
            {
                view.SetErrors(validationResult.Errors);
            }
            else
            {
                view.ClearErrors();
            }

            view.ShowOverrideEditor();
        }
    }

    internal enum EditMode
    {
        Add,
        Update
    }
}